package cn.rjzjh.tapestry.busi.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.rjzjh.commons.util.apiext.CollectionUtil;
import cn.rjzjh.commons.util.assistbean.EasyUINode;
import cn.rjzjh.commons.util.assistbean.EasyUINodeConf;
import cn.rjzjh.commons.util.callback.IConvertValue;
import cn.rjzjh.commons.util.web.EasyUiAssist;
import cn.rjzjh.commons.util.web.OperateResult;
import cn.rjzjh.tapestry.busi.constant.UnitType;
import cn.rjzjh.tapestry.busi.model.ca.CaOrganization;
import cn.rjzjh.tapestry.busi.model.ca.CaResType;
import cn.rjzjh.tapestry.busi.model.ca.CaResource;
import cn.rjzjh.tapestry.busi.model.ca.CaRole;
import cn.rjzjh.tapestry.busi.model.ca.CaRoleAssign;
import cn.rjzjh.tapestry.busi.model.ca.CaStaff;
import cn.rjzjh.tapestry.busi.service.IMenuService;
import cn.rjzjh.tapestry.busi.service.IOrgService;
import cn.rjzjh.tapestry.busi.service.IStaffService;
import cn.rjzjh.tapestry.component.constant.list.YesOrNo;
import cn.rjzjh.tapestry.hibernate.services.IHbService;

@Service
@SuppressWarnings("unchecked")
public class CAServiceImpl implements IStaffService, IMenuService, IOrgService {
	public static Logger logger = LoggerFactory.getLogger(CAServiceImpl.class);

	@Autowired
	@Inject
	private IHbService hbService;
	@Autowired
	@Inject
	private Session session;

	@Override
	public List<CaStaff> findValidStaff(CaStaff caStaff) {
		caStaff.setIsValid(YesOrNo.yes.name());
		List<CaStaff> rets = hbService.findByExample(caStaff);
		return rets;
	}

	@Override
	public CaStaff findValidStaff(int id) {
		CaStaff caStaff = hbService.findById(CaStaff.class, 1);
		if (YesOrNo.yes.name().equals(caStaff.getIsValid())) {
			return caStaff;
		}
		return null;
	}

	@Override
	public List<CaRole> findRolesByStaff(int staffId) {
		Query query = hbService.getQuerySQL("select queryRolesByStaff(?)");
		query.setParameter(0, staffId);
		String rollIds = (String) query.uniqueResult();// TODO
		String[] rollAry = StringUtils.isNotBlank(rollIds)?rollIds.split(","):new String[0];
		List<Integer> rolesParm = CollectionFactory.newList();
		for (String ele : rollAry) {
			rolesParm.add(Integer.parseInt(ele));
		}
		// 要递除的角色
		CaStaff caStaff = (CaStaff) session.get(CaStaff.class, staffId);
		final String[] minRols = StringUtils.isEmpty(caStaff.getMinusRole()) ? new String[0]
				: caStaff.getMinusRole().split("|");
		CollectionUtils.filter(rolesParm, new Predicate() {
			@Override
			public boolean evaluate(Object object) {
				Integer id = (Integer) object;
				return !ArrayUtils.contains(minRols, String.valueOf(id));
			}
		});

		List<CaRole> retList = findRoles(rolesParm);
		return retList;
	}

	private List<CaRole> findRoles(List<Integer> roleIds) {
		if (CollectionUtils.isNotEmpty(roleIds)) {
			Query queryroles = hbService
					.getQuery("from CaRole where id in (:ids) and isValid='yes'");
			queryroles.setParameterList("ids", roleIds);
			List<CaRole> retList = queryroles.list();
			return retList;
		}
		return CollectionFactory.newList();
	}

	@Override
	public List<CaResource> findAllModule(List<CaRole> roles, boolean isRoot) {
		if (CollectionUtils.isEmpty(roles)) {
			return CollectionFactory.newList();
		}
		boolean isDev = isDev(roles);
		Criteria criteria = session.createCriteria(CaResource.class, "cr")
				.createAlias("caRoleReses", "crs");
		if (isRoot) {
			criteria.add(Restrictions.eq("cr.resLevel", 1));
		} else {
			criteria.add(Restrictions.gt("cr.resLevel", 1));
		}
		if (!isDev) {// 不是开发者
			criteria.add(Restrictions.in("crs.caRole", roles));
		}
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		criteria.addOrder(Order.asc("cr.showOrder"));
		List<CaResource> retlist = criteria.list();
		return retlist;
	}

	@Override
	public List<EasyUINode> findModuleMenuForRoles(final int moduleId,
			List<CaRole> roles, IConvertValue I18NConvert) {
		// 查询该用户的所有模块资源
		List<CaResource> resList = this.findAllModule(roles, false);
		EasyUINodeConf conf = new EasyUINodeConf("id", "resName",
				"caResource.id");
		conf.setAttrCols("resValue","caResType.id");
		conf.setIsRoot(new Predicate() {
			@Override
			public boolean evaluate(Object object) {
				int parentId = Integer.parseInt(String.valueOf(object));
				return parentId == moduleId;
			}
		});
		conf.setTextConvert(I18NConvert);
		List<EasyUINode> ret = CollectionFactory.newList();
		try {
			ret = EasyUiAssist.getTreeRoot(resList, conf);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ret;
	}

	private boolean isDev(List<CaRole> roles) {
		boolean isDev = false;
		for (CaRole caRole : roles) {
			if (caRole.getId() == 0) {
				isDev = true;
				break;
			}
		}
		return isDev;
	}

	@Override
	public List<EasyUINode> findAllModuleMenu(IConvertValue i18NConvert,
			boolean hasUnallot) {
		Criteria criteria = session.createCriteria(CaResource.class);
		criteria.add(Restrictions.gt("resLevel", 0));
		if (!hasUnallot) {
			criteria.add(Restrictions.isNotNull("caResource"));// 父节点不能为空
		}
		List<CaResource> resList = criteria.list();
		EasyUINodeConf conf = new EasyUINodeConf("id", "resName",
				"caResource.id", "showOrder");
		conf.setTextConvert(i18NConvert);
		conf.setIconClsCol("icon");
		conf.setAttrCols("caResType.id", "resLevel", "canEdit", "resCode",
				"resName", "resValue", "remark");

		conf.setIsRoot(new Predicate() {
			@Override
			public boolean evaluate(Object object) {
				int parentId = Integer.parseInt(String.valueOf(object));
				return parentId == 1;// 设置所有的模块为树的根
			}
		});

		if (hasUnallot) {
			// 构造虚拟的节点
			CaResource unAllot = new CaResource(-1);
			unAllot.setResName("未分配的资源");
			unAllot.setResValue("0");
			unAllot.setCaResType(new CaResType(6));
			unAllot.setIcon("icon-folder-star");
			unAllot.setResLevel(1);
			unAllot.setCanEdit("no");
			unAllot.setCaResource(new CaResource(1));
			unAllot.setShowOrder(10000);
			resList.add(unAllot);
			// 把未分配的节点全放到它目录下
			for (CaResource res : resList) {
				if (res.getCaResource() == null) {
					res.setCaResource(unAllot);
				}
			}
		}

		List<EasyUINode> ret = CollectionFactory.newList();
		try {
			ret = EasyUiAssist.getTreeRoot(resList, conf);
		} catch (Exception e) {
			logger.error("构造资源树出错", e);
		}
		return ret;
	}

	@Override
	public List<CaResType> findCanEditResType() {
		List<CaResType> resList = hbService
				.getQuery(
						"select new CaResType(id,resTypeCode) from CaResType where id>=3")
				.list();
		return resList;
	}

	@Override
	public List<CaResource> findSyncRes() {
		List<CaResource> resList = hbService.getQuery(
				"from CaResource where resLevel>1 and resType=3").list();
		return resList;
	}

	@Override
	public List<CaRole> findValidRole() {
		List<CaRole> retlist = hbService.getQuery(
				"from CaRole where isValid='yes'").list();
		return retlist;
	}

	@Override
	public String createOrgTree(IConvertValue i18nConvert) {
		List<CaOrganization> orglist = hbService
				.getQuery("from CaOrganization").list();
		if (CollectionUtils.isNotEmpty(orglist)) {
			EasyUINodeConf conf = new EasyUINodeConf("id", "orgName",
					"caOrganization.id");
			conf.setTextConvert(i18nConvert);
			// conf.setIconClsCol(":icon-dept");//设置节点图标为 部门
			conf.setAttrCols("unitType", "orgPath");
			try {
				List<EasyUINode> roots = EasyUiAssist
						.getTreeRoot(orglist, conf);
				if (CollectionUtils.isNotEmpty(roots)) {
					Map<String, EasyUINode> nodes = roots.get(0).getSubs();// 因为只有一根根节点
					roots.get(0).setIconCls("icon-org");// 设置根节点为 机构的图标
					for (String nodeId : nodes.keySet()) {
						EasyUINode node = nodes.get(nodeId);
						UnitType unitType = UnitType.findByName(node
								.getAttribute("unitType"));
						switch (unitType) {
						case ORG:
							node.setIconCls("icon-org");
							break;
						case DEPT:
							node.setIconCls("icon-dept");
							break;
						default:
							break;
						}
					}
				}
				String retstr = EasyUiAssist.getTreeFromList(roots);
				return retstr;
			} catch (Exception e) {
				logger.error("构造组织树出错", e);
			}
		}
		return "[]";
	}

	@Override
	public OperateResult delOrg(Integer orgid) {
		if (orgid == null) {
			return new OperateResult(0, "需要组织ID");
		}
		CaOrganization delobj = (CaOrganization) session.get(
				CaOrganization.class, orgid);
		if (CollectionUtils.isNotEmpty(delobj.getCaOrganizations())) {
			return new OperateResult(0, "此组织有子组织,不允许被删除");
		}
		hbService
				.getQuery(
						"update CaStaff set caOrganization=? where caOrganization.id=?")
				.setParameter(0, null).setParameter(1, delobj.getId())
				.executeUpdate();

		session.delete(delobj);
		return new OperateResult(1);
	}

	@Override
	public List<CaRole> findRolesByUnit(UnitType unitType, int objId,
			Boolean includeAncest) {
		int[] all = new int[0];
		if (includeAncest) {
			List<CaOrganization> allorg = findAncestOrg(objId);
			if (CollectionUtils.isNotEmpty(allorg)) {
				for (CaOrganization org : allorg) {
					int[] temp = findRoleIdsByUnit(
							unitType.findByName(org.getUnitType()), org.getId());
					for (int i = 0; i < temp.length; i++) {
						if (!ArrayUtils.contains(all, temp[i])) {
							all = ArrayUtils.add(all, temp[i]);
						}
					}
				}
			}
		} else {
			int[] temp = findRoleIdsByUnit(unitType, objId);
			for (int i = 0; i < temp.length; i++) {
				if (!ArrayUtils.contains(all, temp[i])) {
					all = ArrayUtils.add(all, temp[i]);
				}
			}
		}
		List<CaRole> retList = findRoles(CollectionUtil.asList(all));
		return retList;
	}

	private int[] findRoleIdsByUnit(UnitType unitType, int objId) {
		List<Integer> roleidlist = hbService
				.getQuery(
						"select caRole.id from CaRoleAssign where assignType=? and assignValue=?")
				.setParameter(0, unitType.name()).setParameter(1, objId).list();
		if (CollectionUtils.isNotEmpty(roleidlist)) {
			int[] ret = new int[roleidlist.size()];
			for (int i = 0; i < ret.length; i++) {
				ret[i] = roleidlist.get(i).intValue();
			}
			return ret;
		}
		return new int[0];
	}

	@Override
	public List<CaOrganization> findAncestOrg(int orgid) {
		CaOrganization curorg = (CaOrganization) session.get(
				CaOrganization.class, orgid);
		String[] orgs = curorg.getOrgPath().split(",");
		Integer[] ids = new Integer[orgs.length];
		for (int i = 0; i < ids.length; i++) {
			ids[i] = Integer.parseInt(orgs[i]);
		}
		Criteria criteria = session.createCriteria(CaOrganization.class);
		criteria.add(Restrictions.in("id", ids));
		List<CaOrganization> retlist = criteria.list();
		return retlist;
	}
}
